﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using InnovTech.Util.Persistence;

namespace NHibernate.Util
{
    public class NHibernateUnitWorker : IUnitWorker
    {
        ISessionFactory _sessFactory;

        public NHibernateUnitWorker(ISessionFactory factory)
        {
            _sessFactory = factory;
        }

        public IInterceptor Interceptor { get; set; }

        public TResult DoUnitOfWork<TResult>(Func<IDao, TResult> action)
        {

            ISession sess = Interceptor == null ?
                _sessFactory.OpenSession() :
                _sessFactory.OpenSession(Interceptor);

            IDao dao = new NHibernateDao(sess);
            TResult result = default(TResult);

            using (var tran = sess.BeginTransaction())
            {
                try
                {
                    result = action(dao);
                    tran.Commit();
                    return result;
                }
                catch
                {
                    if (tran != null && tran.IsActive)
                        tran.Rollback();
                    throw;
                }
                finally
                {
                    if (sess.IsOpen)
                        sess.Close();
                }
            }
            

        }

        public void Save(params object[] toSaveList)
        {
            DoUnitOfWork<object>(dao =>
            {
                dao.Save(toSaveList);
                return null;
            });
        }

        public void Delete(params object[] toDeleteList)
        {
            DoUnitOfWork<object>(dao =>
            {
                dao.Delete(toDeleteList);
                return null;
            });
        }

        public T Get<T>(object id)
        {
            return DoUnitOfWork<T>(dao => dao.Get<T>(id));
        }

        public IEnumerable<T> List<T>(Func<T, bool> predicate)
        {
            return DoUnitOfWork<IEnumerable<T>>(dao => dao.List<T>(predicate).ToList());
        }

        public int Count<T>(Func<T, bool> predicate)
        {
            return DoUnitOfWork<int>(dao => dao.List<T>(predicate).Count());
        }
    }
}
